<!DOCTYPE HTML>
<html>
<head>
  <title>MSE: basic functionality</title>
  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
  <script type="text/javascript" src="mediasource.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">

SimpleTest.waitForExplicitFinish();

runWithMSE(function () {
  SimpleTest.doesThrow(() => new SourceBuffer, "new SourceBuffer should fail");
  SimpleTest.doesThrow(() => new SourceBufferList, "new SourceBufferList direct should fail");

  var ms = new MediaSource();
  ok(ms, "Create a MediaSource object");
  ok(ms instanceof EventTarget, "MediaSource must be an EventTarget");
  is(ms.readyState, "closed", "New MediaSource must be in closed state");

  // Wrapper creation, tests for leaks.
  SpecialPowers.wrap(ms);

  // Set an expando to force wrapper creation, tests for leaks.
  ms.foo = null;

  var o = URL.createObjectURL(ms);
  ok(o, "Create an objectURL from the MediaSource");

  var v = document.createElement("video");
  v.preload = "auto";
  v.src = o;
  document.body.appendChild(v);

  var loadedmetadataCount = 0;
  var updatestartCount = 0;
  var updateendCount = 0;
  var updateCount = 0;

  ms.addEventListener("sourceopen", function () {
    ok(true, "Receive a sourceopen event");
    is(ms.readyState, "open", "MediaSource must be in open state after sourceopen");
    var sb = ms.addSourceBuffer("video/webm");
    ok(sb, "Create a SourceBuffer");
    is(ms.sourceBuffers.length, 1, "MediaSource.sourceBuffers is expected length");
    is(ms.sourceBuffers[0], sb, "SourceBuffer in list matches our SourceBuffer");
    is(ms.activeSourceBuffers.length, 0, "MediaSource.activeSourceBuffers is expected length");


    fetchWithXHR("seek.webm", function (arrayBuffer) {
      sb.appendBuffer(new Uint8Array(arrayBuffer));
      is(sb.updating, true, "SourceBuffer.updating is expected value after appendBuffer");
    });

    sb.addEventListener("update", function () {
      is(sb.updating, false, "SourceBuffer.updating is expected value in update event");
      updateCount++;
      /* Ensure that we endOfStream on the first update event only as endOfStream can
         raise more if the duration of the last buffered range and the intial duration
         differ. See bug 1065207 */
      if (updateCount == 1) {
        ms.endOfStream();
      }
    });

    sb.addEventListener("updatestart", function () {
      updatestartCount++;
    });

    sb.addEventListener("updateend", function () {
      is(ms.activeSourceBuffers[0], sb, "SourceBuffer in active list matches our SourceBuffer");
      is(sb.updating, false, "SourceBuffer.updating is expected value in updateend event");
      updateendCount++;
      v.play();
    });
  });

  ms.addEventListener("sourceended", function () {
    ok(true, "Receive a sourceended event");
    is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended");
  });

  v.addEventListener("loadedmetadata", function () {
    loadedmetadataCount++;
  });

  v.addEventListener("ended", function () {
    // XXX: Duration should be exactly 4.0, see bug 1065207.
    ok(Math.abs(v.duration - 4) <= 0.002, "Video has correct duration");
    ok(Math.abs(v.currentTime - 4) <= 0.002, "Video has played to end");
    // XXX: 2 update events can be received dueto duration differences, see bug 1065207.
    ok(updateCount == 1 || updateCount == 2, "update event received");
    ok(updateendCount == 1 || updateendCount == 2, "updateend event received");
    ok(updatestartCount == 1 || updatestartCount == 2, "updatestart event received");
    is(loadedmetadataCount, 1, "loadedmetadata event received");
    v.parentNode.removeChild(v);
    SimpleTest.finish();
  });
});

</script>
</pre>
</body>
</html>
